
package com.fdb.efp.cus.api.rest;

import com.alibaba.fastjson.JSON;
import com.gdrcu.efp.cus.common.ExcelException;
import com.gdrcu.efp.cus.common.util.ExcelImportUtil;
import com.fdb.basic.framework.core.constant.ApplicationConstance;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.util.UUIDUtil;
import com.fdb.basic.framework.web.controller.AbstractController;
import com.fdb.efp.console.service.facade.SUserService;
import com.fdb.efp.cus.api.common.YedCompanyClassEnum;
import com.fdb.efp.cus.api.common.YedCompanyOnwayEnum;
import com.fdb.efp.cus.api.common.YedCompanyTypeEnum;
import com.fdb.efp.cus.api.service.CusToolService;
import com.fdb.efp.cus.service.facade.CompanyWhiteListService;
import com.fdb.efp.cus.service.vo.CompanyWhiteListVO;

import com.fdb.efp.cus.service.vo.CompanyWhiteExcelVO;
import com.fdb.efp.cus.service.vo.CompanyWhiteDeleteExcelVO;

import org.apache.commons.fileupload.disk.DiskFileItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api")
public class CompanyWhiteListController extends AbstractController {

	@Autowired
	@Qualifier("companyWhiteListService")
	private CompanyWhiteListService companyWhiteListService;

	@Autowired
	@Qualifier("sUserService")
	private SUserService sUserService;

	@Autowired
	@Qualifier("cusToolService")
	private CusToolService cusToolService;

	private List<CompanyWhiteExcelVO> errorHisDuplicateDataList = new ArrayList<>();
	private List<CompanyWhiteExcelVO> singleRowList = new ArrayList<>();

	private List<CompanyWhiteDeleteExcelVO> errorHisDuplicateDataListD = new ArrayList<CompanyWhiteDeleteExcelVO>();
	private List<CompanyWhiteDeleteExcelVO> singleRowListD = new ArrayList<CompanyWhiteDeleteExcelVO>();

	private static Logger logger = LoggerFactory.getLogger(PersonalWhiteListController.class);

	private static final String CONTENTTYPE = "application/json;charset=UTF-8";

	private static final String MODELNAME = "企业白名单更新模板.xls";

	private static final String SHEET1NAME = "企业白名单上传";

	private static final String IMPORT_PATH = "/template/compWhUpList.xls";

	private static final String MODELNAME1 = "企业白名单删除模板.xls";

	private static final String SHEET1NAME1 = "企业白名单删除";

	private static final String IMPORT_PATH1 = "/template/compWhDeList.xls";

	/**
	 * 列表数据查询
	 * @return
	 */
	@RequestMapping(value="/company/white/lists", method= RequestMethod.POST)
	public @ResponseBody
	ResponseData<List<CompanyWhiteListVO>> queryPersonalWhiteListAll(@RequestBody CompanyWhiteListVO vo) {
		List<CompanyWhiteListVO> outputVo = companyWhiteListService.queryAllList(vo);

		cusToolService.displayOrgName(outputVo,"appearOrg","appearName");

		return getResponseData(outputVo);
	}

	@RequestMapping(value = "/query/company/effectiveDate", method = RequestMethod.POST)
	public @ResponseBody ResponseData<Integer> queryEffectiveDt() {
		int outputVo = companyWhiteListService.effectiveDate();
		return getResponseData(outputVo);
	}

/**
 * 根据企业id批量删除信息
 * @return
 */

	@RequestMapping(value = "/company/white/list/delete", method = RequestMethod.DELETE)
	public @ResponseBody ResponseData<Integer> batchDeleteById(@RequestBody CompanyWhiteListVO vo) {
		int outputVo = companyWhiteListService.batchDeleteByCompanyId(vo);
		return getResponseData(outputVo);
	}

	/**
	 * 下载导入更新模板
	 * @return
	 */
	@RequestMapping(value="/company/white/up/downLoad", method=RequestMethod.GET)
	public @ResponseBody ResponseData<String> pWUDownLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			response.setContentType(CONTENTTYPE);
			/**
			 * getBytes()，需要声明一下读取的编码方式，不然IE浏览器，会出现文件名乱码，谷歌不会
			 * 【解决方法】 getBytes("GBK")
			 */
			response.setHeader("Content-Disposition", "attachment;filename="+  new String((MODELNAME).getBytes("GBK"), "ISO8859-1"));
			ServletOutputStream out = response.getOutputStream();
			logger.info("下载企业白名单上传更新模板开始----------------------------");
			bis = new BufferedInputStream(PersonalWhiteListController.class.getClassLoader().getResourceAsStream(IMPORT_PATH));
			bos = new BufferedOutputStream(out);
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			logger.error("企业白名单上传更新模板下载失败：" , e);
			return getResponseData(null);
		} finally {
			if(null != bis) {
				bis.close();
			}
			if(null != bos){
				bos.close();
			}
		}
		logger.info("下载企业白名单上传更新模板结束。。。。。。。。。。。。。。。。。。。");
		return getResponseData("success!");
	}

	/**
	 * 下载导入删除模板
	 * @return
	 */
	@RequestMapping(value="/company/white/delete/downLoad", method=RequestMethod.GET)
	public @ResponseBody ResponseData<String> dWUDownLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			response.setContentType(CONTENTTYPE);

			/**
			 * getBytes()，需要声明一下读取的编码方式，不然IE浏览器，会出现文件名乱码，谷歌不会
			 * 【解决方法】 getBytes("GBK")
			 */

			response.setHeader("Content-Disposition", "attachment;filename="+  new String((MODELNAME1).getBytes("GBK"), "ISO8859-1"));
			ServletOutputStream out = response.getOutputStream();
			logger.info("下载企业白名单删除模板开始----------------------------");
			bis = new BufferedInputStream(PersonalWhiteListController.class.getClassLoader().getResourceAsStream(IMPORT_PATH1));
			bos = new BufferedOutputStream(out);
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			logger.error("企业白名单删除模板下载失败：" , e);
			return getResponseData(null);
		} finally {
			if(null != bis) {
				bis.close();
			}
			if(null != bos){
				bos.close();
			}
		}
		logger.info("下载企业白名单删除模板结束。。。。。。。。。。。。。。。。。。。");
		return getResponseData("success!");
	}

	/**
	 * 设置有效日期
	 * @return
	 */
	@RequestMapping(value = "/company/white/setDt", method = RequestMethod.PUT)
	public @ResponseBody ResponseData<Integer> setEffDtById(@RequestBody CompanyWhiteListVO companyWhiteListVO) {

		int outputVo = companyWhiteListService.upDateToSetDt(companyWhiteListVO);
		return getResponseData(outputVo);

	}

	/****************************************导入更新开始**************************************************/
	/**
	 * 导入更新
	 * @return
	 */
	@RequestMapping(value="/company/white/list/upload", method=RequestMethod.POST)
	public void  personalWhiteListUpload(HttpServletResponse respone, HttpServletRequest request) {
		ResponseData<List<CompanyWhiteListVO>> result = new ResponseData<List<CompanyWhiteListVO>>();
		List<File> companyWhiteList = new ArrayList<File>();
		respone.setContentType(CONTENTTYPE);
		OutputStream out = null;
		int total = 0;
		int illegal = 0;
		int repeatNum = 0;
		try {
			out = respone.getOutputStream();
			//获取文件
			companyWhiteList = getFileList(request);
			if(!companyWhiteList.isEmpty()){
				for(File file : companyWhiteList){
					/**
					 * 将Excel文件解析成对应实体Bean
					 */
					List<CompanyWhiteExcelVO> companyWhiteExcList = ExcelImportUtil.importExcelByClass(SHEET1NAME, file, CompanyWhiteExcelVO.class);

					if(companyWhiteExcList.size()>0){
						//检查历史数据是否重复
						String errStr = "";
						errStr = checkHisDatas(companyWhiteExcList);
						//组装数据
						List<CompanyWhiteListVO> insertListBatch = new ArrayList<CompanyWhiteListVO>();
						insertListBatch =  assembleData(singleRowList);
						//批量插入
						//执行插入操作
						int num = 0;
						if (insertListBatch.size() > 0) num = execBatchInsertSql(insertListBatch);
						if (num < 0) throw new Exception("插入数据出错！");
						//错误信息
						if (!StringUtil.isNullorBank(errStr)) {
							errStr = "ExcelError:" + errStr;
							throw new Exception(errStr);
						}
						//组装结果
						result = getResponseData(insertListBatch);
					}else{
						result = result.createData(null, ApplicationConstance.FAILURE, "文件内容为空", false);
					}
				}
			}else{
				throw new ExcelException("获取不到上传的文件！");
			}
		} catch (Exception e) {
			logger.error("文件上传失败,失败原因:", e);
			result = result.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
		} finally {
			String str = JSON.toJSONString(result);
			try {
				out.write(str.getBytes(Charset.forName("UTF-8")));
				out.flush();
				out.close();
			} catch (IOException e) {
				logger.error("关闭数据流OutputStream出错，错误信息为：", e);
			}
		}
	}

	private String checkHisDatas(List<CompanyWhiteExcelVO> checkExcelVOList) throws Exception {
		int errorRow = 4;
		List<Integer> errorDuplicateRowList = new ArrayList<>();
		String errorDuplicateMsg = "";
		errorHisDuplicateDataList.clear();
		Map<Integer, String> errorList = new HashMap<Integer, String>();
		String errorLoanUnpdPriMsg = "";

		for (CompanyWhiteExcelVO item : checkExcelVOList) {
			if ("".equals(item.getCompanyName()) || item.getCompanyName()==null ){
				//indexErr.add(index);
				errorLoanUnpdPriMsg = "导入的Excel文档第【" + errorRow + "】行数据企业名称为空";
				logger.info("数据错误：" + errorLoanUnpdPriMsg);
				collError(errorList,errorRow,errorLoanUnpdPriMsg);

				errorHisDuplicateDataList.add(item);
			}else if(!Optional.ofNullable(YedCompanyTypeEnum.getEnum(item.getCompanyType())).isPresent()){
				errorLoanUnpdPriMsg = "导入的Excel文档第【" + errorRow + "】行数据企业类别字典项不正确";
				logger.info("数据错误：" + errorLoanUnpdPriMsg);
				collError(errorList,errorRow,errorLoanUnpdPriMsg);

				errorHisDuplicateDataList.add(item);
			}else if(!Optional.ofNullable(YedCompanyOnwayEnum.getEnum(item.getStatus())).isPresent()){
				errorLoanUnpdPriMsg = "导入的Excel文档第【" + errorRow + "】行数据企业经营状态字典项不正确";
				logger.info("数据错误：" + errorLoanUnpdPriMsg);
				collError(errorList,errorRow,errorLoanUnpdPriMsg);

				errorHisDuplicateDataList.add(item);
			}else if(!Optional.ofNullable(YedCompanyClassEnum.getEnum(item.getCompanyClass())).isPresent()){
				errorLoanUnpdPriMsg = "导入的Excel文档第【" + errorRow + "】行数据企业分类字典项不正确";
				logger.info("数据错误：" + errorLoanUnpdPriMsg);
				collError(errorList,errorRow,errorLoanUnpdPriMsg);

				errorHisDuplicateDataList.add(item);
			}else{
				boolean flag = checkDataIsUnique(item);
				if (flag) {
					//errorDuplicateRowList.add(errorRow);
					errorHisDuplicateDataList.add(item);

					//数据存在则更新
					updateCompanyWhite(item);
				}
			}
			errorRow++;
		}

		//收集没问题的导入数据
		singleRowList.clear();
		singleRowList = checkExcelVOList.stream().filter(a->!errorHisDuplicateDataList.contains(a)).collect(Collectors.toList());

		//按key值对errorList排序并将value拼接成字符串
		String rs = "";
		rs += sortAndSpliceMap(errorList);
		return rs;
	}
	/**
	 * 查询数据是否存在
	 */
	private boolean checkDataIsUnique(CompanyWhiteExcelVO item) throws Exception {
		CompanyWhiteListVO param = new CompanyWhiteListVO();
		param.setCompanyName(item.getCompanyName());
		List<CompanyWhiteListVO> queryRs = companyWhiteListService.queryConditions(param);
		return  Objects.isNull(queryRs) ? false : true;
	}
	/**
	 * 存在则更新该条记录
	 */
	private int updateCompanyWhite(CompanyWhiteExcelVO companyExcel) {
		int num = 0;
		CompanyWhiteListVO updateCompany = new CompanyWhiteListVO();
		updateCompany.setCompanyName(companyExcel.getCompanyName());
		updateCompany.setRegisterTime(companyExcel.getRegisterTime());
		updateCompany.setCompanyType(companyExcel.getCompanyType());
		updateCompany.setStatus(companyExcel.getStatus());
		updateCompany.setCompanyClass(companyExcel.getCompanyClass());
		updateCompany.setAppearOrg(companyExcel.getAppearOrg());

		setUserInfoToVO(companyExcel);
		String currDt = TimeUtil.getCurrentDateTime();
		String currDt1 = currDt.substring(0,10);
		String currDt2 = currDt.substring(11);

		String userId = companyExcel.getLoginUserId();
		String userName = queryUserName(userId);
        //最后更新日期
		updateCompany.setUpdateDate(currDt1);
		//最后更新时间
		updateCompany.setUpdateTime(currDt2);
		//最后更新人员
		updateCompany.setUpdateNo(userId);
		//最后更新人员名称
		updateCompany.setUpdateName(userName);

		return num = companyWhiteListService.updateCompany(updateCompany);
	}

	@SuppressWarnings("rawtypes")
	private List<File> getFileList(HttpServletRequest request) throws IOException{
		List<File> listFiles = new ArrayList<File>();
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
		if(multipartResolver.isMultipart(request)){
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			Iterator iter = multiRequest.getFileNames();
			while(iter.hasNext()) {
				MultipartFile mFile = multiRequest.getFile(iter.next().toString());
				if(mFile != null){
					listFiles.add(multipartToFile(mFile));
				}
			}
		}
		return listFiles;
	}

	private File multipartToFile(MultipartFile multfile) throws IOException {
		CommonsMultipartFile cmf = (CommonsMultipartFile)multfile;
		DiskFileItem dfi = (DiskFileItem) cmf.getFileItem();
		File file = dfi.getStoreLocation();
		if(file.length() < 2048){
			File tmpFile = new File(System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") +  file.getName());
			multfile.transferTo(tmpFile);
			return tmpFile;
		}
		return file;
	}

	private List<CompanyWhiteListVO> assembleData(List<CompanyWhiteExcelVO> companyWhiteExcelVO) throws Exception {
		List<CompanyWhiteListVO> list = new ArrayList<>();
		if (Objects.nonNull(companyWhiteExcelVO)) {
			CompanyWhiteListVO companyWhiteParam = new CompanyWhiteListVO();
			setUserInfoToVO(companyWhiteParam);
			String currDt = TimeUtil.getCurrentDateTime();
			String currDt1 = currDt.substring(0,10);
			String currDt2 = currDt.substring(11);

			String userId = companyWhiteParam.getLoginUserId();
			String userName = queryUserName(userId);

			Iterator<CompanyWhiteExcelVO> iterator = companyWhiteExcelVO.iterator();
			while(iterator.hasNext()) {
				CompanyWhiteExcelVO tempExcelVO = iterator.next();
				CompanyWhiteListVO companyWhiteListVO = new CompanyWhiteListVO();

				//企业id
				companyWhiteListVO.setCompanyId(UUIDUtil.getUUID());
				//设置企业名称
				companyWhiteListVO.setCompanyName(tempExcelVO.getCompanyName());
				companyWhiteListVO.setRegisterTime(tempExcelVO.getRegisterTime());
				companyWhiteListVO.setCompanyType(tempExcelVO.getCompanyType());
				companyWhiteListVO.setStatus(tempExcelVO.getStatus());
				companyWhiteListVO.setCompanyClass(tempExcelVO.getCompanyClass());
				companyWhiteListVO.setAppearOrg(tempExcelVO.getAppearOrg());

				//导入日期
				companyWhiteListVO.setImportDate(currDt1);
				//导入时间
				companyWhiteListVO.setImportTime(currDt2);
				//导入人员工号
				companyWhiteListVO.setImportEmpNo(userId);
				//导入人员名称
				companyWhiteListVO.setImportEmpName(userName);
				//最后更新日期
				companyWhiteListVO.setUpdateDate(currDt1);
				//最后更新时间
				companyWhiteListVO.setUpdateTime(currDt2);
				//最后更新人员
				companyWhiteListVO.setUpdateNo(userId);
				//最后更新人员名称
				companyWhiteListVO.setUpdateName(userName);

				list.add(companyWhiteListVO);
			}
		} else {
			throw new ExcelException("获取数据为空!");
		}
		return list;
	}

	private int execBatchInsertSql(List<CompanyWhiteListVO> inserListBatch) {
		int num = 0;
		return num = companyWhiteListService.batchInsertList(inserListBatch);
	}

	private String sortAndSpliceMap(Map<Integer, String> errorList) {
		String rs = "";
		//取出key值，根据key值排序
		Object[] key = errorList.keySet().toArray();
		Arrays.sort(key);
		//拼接信息
		Iterator ite = errorList.entrySet().iterator();
		while (ite.hasNext()) {
			Map.Entry string = (Map.Entry) ite.next();
			StringBuffer buffer = new StringBuffer();
			if (StringUtil.isNullorBank(rs)) {
				rs = (String) string.getValue();
			} else {
				rs = buffer.append(rs).append(",").append(string.getValue()).toString();
			}
		}
		return rs;
	}
	private void collError(Map<Integer, String> errorMap, Integer integer, String str) {
		if (errorMap.containsKey(integer)) {
			integer += 1;
			collError(errorMap,integer,str);
		} else {
			errorMap.put(integer,str);
		}
	}

	/**
	 * 根据用户号查用户名称
	 */
	public String queryUserName(String userId){
		String userName = "";
		userName = sUserService.queryUserNameByUserId(userId);
		return userName;
	}

	/****************************************导入更新结束**************************************************/

	/****************************************导入删除开始**************************************************/
	/**
	 * 导入删除文件
	 */
	@SuppressWarnings("resource")
	@RequestMapping(value="/company/white/import/delete", method=RequestMethod.POST)
	public void  personalWhiteListDelete(HttpServletResponse respone, HttpServletRequest request) {
		ResponseData<List<CompanyWhiteListVO>> result = new ResponseData<List<CompanyWhiteListVO>>();
		List<File> companyWhiteList = new ArrayList<File>();
		respone.setContentType(CONTENTTYPE);
		OutputStream out = null;

		String errorLoanUnpdPriMsg = "";
		int errorRow = 4;
		Map<Integer, String> errorList = new HashMap<Integer, String>();

		String rs = "";

		try {
			out = respone.getOutputStream();
			//获取文件
			companyWhiteList = getFileList(request);
			if(!companyWhiteList.isEmpty()){
				for(File file : companyWhiteList){
					/**
					 * 将Excel文件解析成对应实体Bean
					 */
					List<CompanyWhiteDeleteExcelVO> companyWhiteDelExcList = ExcelImportUtil.importExcelByClass(SHEET1NAME1, file, CompanyWhiteDeleteExcelVO.class);
					//批量删除数据
					if(companyWhiteDelExcList.size() > 0 ){
						for(CompanyWhiteDeleteExcelVO item : companyWhiteDelExcList){
							CompanyWhiteListVO param = new CompanyWhiteListVO();
							param.setCompanyName(item.getCompanyName());
							List<CompanyWhiteListVO> queryRs = companyWhiteListService.queryConditions(param);
							if(Objects.isNull(queryRs)) {
								errorLoanUnpdPriMsg = "导入的Excel文档第【" + errorRow + "】行数据企业名称不存在";
								logger.info("数据错误：" + errorLoanUnpdPriMsg);
								collError(errorList,errorRow,errorLoanUnpdPriMsg);
							}
							errorRow++;
						}

						rs += sortAndSpliceMap(errorList);
						companyWhiteListService.batchDelCompanyWhiteByExcel(companyWhiteDelExcList);
						List<CompanyWhiteListVO> deleteListBatch = new ArrayList<CompanyWhiteListVO>();
						deleteListBatch =  assembleDelteData(singleRowListD);

						//错误信息
						if (!StringUtil.isNullorBank(rs)) {
							rs = "ExcelError:" + rs;
							throw new Exception(rs);
						}
						result = getResponseData(deleteListBatch);
					}else{
						result = result.createData(null, ApplicationConstance.FAILURE, "文件内容为空", false);
					}
				}
			}else{
				throw new ExcelException("获取不到上传的文件！");
			}
		} catch (Exception e) {
			logger.error("文件上传失败,失败原因:", e);
			result = result.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
		} finally {
			String str = JSON.toJSONString(result);
			try {
				out.write(str.getBytes(Charset.forName("UTF-8")));
				out.flush();
				out.close();
			} catch (IOException e) {
				logger.error("关闭数据流OutputStream出错，错误信息为：", e);
			}
		}
	}

	private List<CompanyWhiteListVO> assembleDelteData(List<CompanyWhiteDeleteExcelVO> companyWhiteDelExcelVO) throws Exception {
		List<CompanyWhiteListVO> list = new ArrayList<>();
		if (Objects.nonNull(companyWhiteDelExcelVO)) {
			Iterator<CompanyWhiteDeleteExcelVO> iterator = companyWhiteDelExcelVO.iterator();

			while(iterator.hasNext()) {
				CompanyWhiteDeleteExcelVO tempExcelVO = iterator.next();
				CompanyWhiteListVO companyWhiteListVO = new CompanyWhiteListVO();

				companyWhiteListVO.setCompanyName(tempExcelVO.getCompanyName());
				list.add(companyWhiteListVO);
			}
		} else {
			throw new ExcelException("获取数据为空!");
		}
		return list;
	}
	/****************************************导入删除结束**************************************************/

}

